package org.ruoyi.common.dhuman.utils;
import edu.cmu.sphinx.api.SpeechAligner;
import edu.cmu.sphinx.result.WordResult;

import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

public class LocalSubtitleGenerator {

	private SpeechAligner aligner;
	private String acousticModelPath;
	private String dictionaryPath;
	private String languageModelPath;

	public LocalSubtitleGenerator(String acousticModelPath,
								  String dictionaryPath,
								  String languageModelPath) {
		this.acousticModelPath = acousticModelPath;
		this.dictionaryPath = dictionaryPath;
		this.languageModelPath = languageModelPath;
	}

	/**
	 * 初始化语音对齐器
	 */
	public void initialize() throws IOException {
		// 对于中文，需要使用相应的中文模型
		// 这里以英文为例，中文模型需要额外下载
		this.aligner = new SpeechAligner(
			acousticModelPath,
			dictionaryPath,
			languageModelPath
		);
	}

	/**
	 * 生成字幕文件的主方法
	 *
	 * @param audioPath 音频文件路径
	 * @param copyText 文本内容
	 * @param outputSrtPath 字幕文件路径
	 * @throws Exception
	 */
	public void generateSubtitles(String audioPath, String copyText, String outputSrtPath)
		throws Exception {

		// 1. 读取文本文件
		System.out.println("原始文本: " + copyText);

		// 2. 预处理文本（分割为句子）
		List<String> sentences = splitIntoSentences(copyText);

		// 3. 如果对齐器不可用，使用基于时间估算的简单方法
		if (aligner == null) {
			System.out.println("使用基于时间的简单对齐方法");
			generateSubtitlesByTimeEstimation(audioPath, sentences, outputSrtPath);
		} else {
			// 4. 使用语音对齐器进行精确对齐
			System.out.println("使用语音对齐器进行精确对齐");
			generateSubtitlesWithAligner(audioPath, copyText, sentences, outputSrtPath);
		}
	}

	/**
	 * 生成字幕文件的主方法
	 *
	 * @param audioPath 音频文件路径
	 * @param textPath 文本文件路径
	 * @param outputSrtPath 字幕文件路径
	 * @throws Exception
	 */
	public void generateSubtitles2(String audioPath, String textPath, String outputSrtPath)
		throws Exception {
		String transcript = readTextFile(textPath);
		generateSubtitles(audioPath, transcript, outputSrtPath);
	}
	/**
	 * 使用语音对齐器进行精确对齐
	 */
	private void generateSubtitlesWithAligner(String audioPath, String transcript,
											  List<String> sentences, String outputSrtPath)
		throws Exception {

		// 对齐整个文本获取单词级别的时间戳
		URL audioUrl = new File(audioPath).toURI().toURL();
		List<WordResult> wordResults = aligner.align(audioUrl, transcript);

		// 将单词结果转换为字幕项
		List<SubtitleItem> subtitleItems = convertToSubtitleItems(wordResults, sentences);

		// 生成SRT文件
		generateSrtFile(subtitleItems, outputSrtPath);

		System.out.println("成功生成字幕文件: " + outputSrtPath);
		System.out.println("共生成 " + subtitleItems.size() + " 条字幕");
	}

	/**
	 * 基于时间估算的简单对齐方法（备用方案）
	 */
	private void generateSubtitlesByTimeEstimation(String audioPath,
												   List<String> sentences,
												   String outputSrtPath)
		throws Exception {

		// 获取音频时长
		long audioDuration = FFmpegAudioUtil.getAudioDuration(audioPath);

		// 计算总字符数用于时间分配
		int totalChars = sentences.stream().mapToInt(String::length).sum();

		List<SubtitleItem> subtitleItems = new ArrayList<>();
		long currentTime = 0;

		for (String sentence : sentences) {
			if (sentence.trim().isEmpty()) {
				continue;
			};

			// 根据字符比例分配时间
			double ratio = (double) sentence.length() / totalChars;
			long sentenceDuration = (long) (audioDuration * ratio);

			// 确保最小显示时间
			// 2秒
			long minDuration = 2000;
			sentenceDuration = Math.max(sentenceDuration, minDuration);

			// 创建字幕项
			SubtitleItem item = new SubtitleItem();
			item.startTime = currentTime;
			item.endTime = currentTime + sentenceDuration;
			item.text = sentence.trim();

			subtitleItems.add(item);
			currentTime += sentenceDuration;
		}

		// 生成SRT文件
		generateSrtFile(subtitleItems, outputSrtPath);
		System.out.println("使用时间估算生成字幕文件: " + outputSrtPath);
	}

	/**
	 * 将单词结果转换为字幕项
	 */
	private List<SubtitleItem> convertToSubtitleItems(List<WordResult> wordResults,
													  List<String> sentences) {
		List<SubtitleItem> subtitleItems = new ArrayList<>();
		int wordIndex = 0;

		for (String sentence : sentences) {
			if (sentence.trim().isEmpty()) {
				continue;
			}

			// 简单的基于单词匹配的句子边界检测
			List<WordResult> sentenceWords = new ArrayList<>();
			String[] sentenceWordArray = sentence.toLowerCase().split("\\s+");

			for (String expectedWord : sentenceWordArray) {
				if (wordIndex < wordResults.size()) {
					WordResult wordResult = wordResults.get(wordIndex);
					String actualWord = wordResult.getWord().getSpelling().toLowerCase();

					// 简单的单词匹配（实际应用中可能需要更复杂的匹配逻辑）
					if (isWordMatch(actualWord, expectedWord)) {
						sentenceWords.add(wordResult);
						wordIndex++;
					}
				}
			}

			if (!sentenceWords.isEmpty()) {
				// 使用句子中第一个和最后一个单词的时间戳
				long startTime = sentenceWords.get(0).getTimeFrame().getStart();
				long endTime = sentenceWords.get(sentenceWords.size() - 1).getTimeFrame().getEnd();

				SubtitleItem item = new SubtitleItem();
				item.startTime = startTime;
				item.endTime = endTime;
				item.text = sentence.trim();

				subtitleItems.add(item);
			}
		}

		return subtitleItems;
	}

	/**
	 * 简单的单词匹配逻辑
	 */
	private boolean isWordMatch(String actual, String expected) {
		// 移除标点符号进行比较
		actual = actual.replaceAll("[^a-zA-Z]", "");
		expected = expected.replaceAll("[^a-zA-Z]", "");
		return actual.equals(expected);
	}

	/**
	 * 读取文本文件
	 */
	private String readTextFile(String filePath) throws IOException {
		if (filePath == null || filePath.isEmpty()) {
			return "";
		}
		File file = new File(filePath);
		if (file != null && !file.exists()) {
			file.createNewFile();
		}
		return new String(Files.readAllBytes(Paths.get(filePath)), "UTF-8");
	}

	/**
	 * 将文本分割为句子
	 */
	private List<String> splitIntoSentences(String text) {
		// 简单的句子分割逻辑，可以根据需要优化
		String[] sentences = text.split("[.!?。！？]\\s*");
		List<String> result = new ArrayList<>();
		for (String sentence : sentences) {
			if (!sentence.trim().isEmpty()) {
				result.add(sentence.trim());
			}
		}
		return result;
	}

	/**
	 * 生成SRT文件
	 */
	public static void generateSrtFile(List<SubtitleItem> items, String outputPath) {
		try (PrintWriter out = new PrintWriter(outputPath, "UTF-8")) {
			for (int i = 0; i < items.size(); i++) {
				SubtitleItem item = items.get(i);

				// 序号
				out.println(i + 1);

				// 时间轴
				String start = formatTime(item.startTime);
				String end = formatTime(item.endTime);
				out.println(start + " --> " + end);

				// 文本
				out.println(item.text);

				// 空行分隔
				out.println();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 格式化时间戳
	 */
	private static String formatTime(long milliseconds) {
		long hours = milliseconds / 3600000;
		long minutes = (milliseconds % 3600000) / 60000;
		long seconds = (milliseconds % 60000) / 1000;
		long millis = milliseconds % 1000;
		return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, millis);
	}

	/**
	 * 字幕项数据模型
	 */
	public static class SubtitleItem {
		public long startTime; // 开始时间（毫秒）
		public long endTime;   // 结束时间（毫秒）
		public String text;    // 字幕文本

		public SubtitleItem() {}

		public SubtitleItem(long startTime, long endTime, String text) {
			this.startTime = startTime;
			this.endTime = endTime;
			this.text = text;
		}
	}
}
